/**
 * 由于微信不支持SSE，而websocket存在不稳定、成本高诸多缺点，权衡之下采用二进制流传输
 * 由于微信分块会截断数据，该类用于高效的合并ArrayBuffer
 */
class DynamicBuffer {

  #initialSize = 1024;
  #buffer;
  #offset = 0; // 当前写入位置
  #last = 0; // 最后一个十进制码

  constructor(initialSize = 1024) {
    this.#initialSize = initialSize;
    this.#buffer = new Uint8Array(this.#initialSize);
  }

  /**
   * 清空
   */
  clear() {
    this.#buffer = new Uint8Array(this.#initialSize);
    this.#offset = 0;
    this.#last = 0;
  }

  /**
   * 追加新数据
   * @param {ArrayBuffer} newBuffer 
   */
  append(newBuffer) {
    let newData = new Uint8Array(newBuffer);
    if (newData.length > 0) {
      // 记录最后一个
      this.#last = newData[newData.length - 1];
      if (this.#last === 4 || this.#last === 21) {
        newData = newData.subarray(0, newData.length - 1);
      }
    }
    // 判断越界
    if (newData.length > Number.MAX_SAFE_INTEGER - this.#offset) {
      throw new Error("数据大小超出最大限制");
    }
    // 检查是否需要扩容
    if (this.#offset + newData.length > this.#buffer.length) {
      this.#expand(this.#offset + newData.length);
    }
    this.#buffer.set(newData, this.#offset);
    this.#offset += newData.length;
  }

  /**
   * 扩容策略（按需翻倍或按实际需求）
   * @param {number} minSize 
   */
  #expand(minSize) {
    const newSize = Math.max(minSize, this.#buffer.byteLength * 2);
    const newBuffer = new Uint8Array(newSize);
    newBuffer.set(this.#buffer.subarray(0, this.#offset));
    this.#buffer = newBuffer;
  }

  /**
   * 获取最终合并的 ArrayBuffer（截取实际长度）
   */
  getMergedBuffer() {
    return this.#buffer.buffer.slice(0, this.#offset);
  }

  /**
   * 获取最后一个十进制
   * 若为4则代表结束(EOT)，21则代表错误(NAK)
   * 注意：一定在获取结果后再读取该值
   */
  getLast() {
    return this.#last;
  }
}

module.exports = DynamicBuffer